package net.mayee.common;

import jodd.log.Logger;
import jodd.log.LoggerFactory;
import net.mayee.alice.entity.permission.Action;
import net.mayee.alice.entity.permission.Permission;
import net.mayee.datatables.DtBean;
import org.apache.commons.lang3.StringUtils;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.InputStream;
import java.util.*;

public class PermissionHelper {

    private static final Logger LOGGER = LoggerFactory.getLogger(PermissionHelper.class);
    private Map<String, Action> globalActionMap;
    private Map<String, Permission> permissionsMap;
    private ArrayList<Action> actionArray;

    private PermissionHelper() {
        initPermissionHelper();
    }

    private static final PermissionHelper permissionHelper = new PermissionHelper();

    public static PermissionHelper getInstance() {
        return permissionHelper;
    }

    private void initPermissionHelper() {
        loadPermissionXml();
    }

    public Map<String, Permission> getPermissionsMap() {
        return permissionsMap;
    }

    public Permission getPermissionByMenuId(String menuId) {
        return permissionsMap.get(menuId);
    }

    public List<Action> searchByLimit(Map<String, Object> paramsMap) {
        ArrayList<Action> result = new ArrayList<Action>(actionArray);

        if (paramsMap.containsKey("menuId")) {
            String menuId = (String) paramsMap.get("menuId");
            /* -1代表全部 */
            if (!"-1".equals(menuId) && permissionsMap.containsKey(menuId)) {
                result = new ArrayList<Action>();
                result.addAll(permissionsMap.get(menuId).getActionList());
            }else{
                return new ArrayList<Action>();
            }
        }

        if (paramsMap.containsKey(DtBean.DT_DEFAULT_SEARCH_KEY)) {
            String searchVal = (String) paramsMap.get(DtBean.DT_DEFAULT_SEARCH_KEY);
            for (int j = 0; j < result.size(); j++) {
                Action action = result.get(j);
                if (action.getText().indexOf(searchVal) < 0
                        && action.getKey().indexOf(searchVal) < 0
                        && action.getNote().indexOf(searchVal) < 0
                        && action.getMenuId().indexOf(searchVal) < 0
                        && action.getMenuName().indexOf(searchVal) < 0) {
                    result.remove(j);
                    j--;
                }
            }
        }

        /* 分页 */
        int offset = (Integer) paramsMap.get("offset");
        int limit = (Integer) paramsMap.get("limit");
        int count = result.size();
        if (count > limit) {
            ArrayList<Action> r = new ArrayList<Action>(10);
            for (int i = 0; i < limit; i++) {
                if (offset + i == count) {
                    break;
                }
                r.add(result.get(offset + i));
            }
            return r;
        }

        return result;
    }

    private List<Action> getAllAction() {
        ArrayList<Action> resultList = new ArrayList<Action>();
        Set<String> keySet = permissionsMap.keySet();
        for (String menuId : keySet) {
            resultList.addAll(permissionsMap.get(menuId).getActionList());
        }
        return resultList;
    }

    public int getPermissionCount() {
        return actionArray.size();
    }

    private void loadPermissionXml() {
        String xmlPath = AliceHelper.getInstance().getJoddProps().getValue("permission.xml.path");
        SAXReader reader = new SAXReader();
        Document document;
        try {
            InputStream in = this.getClass().getResourceAsStream(xmlPath);
            document = reader.read(in);
        } catch (Exception e) {
            LOGGER.error("**** PermissionHelper -> loadPermissionXml fail! ****", e);
            return;
        }

        /* new or reset */
        globalActionMap = new HashMap<String, Action>();
        permissionsMap = new HashMap<String, Permission>();
        actionArray = new ArrayList<Action>();

        Element root = document.getRootElement();
        for (Iterator iterA = root.elementIterator(); iterA.hasNext(); ) {
            // 获取节点 globalActions / permissions
            Element elementA = (Element) iterA.next();
            if (elementA != null && elementA.hasContent()) {
                if ("globalActions".equals(elementA.getName())) {
                    // 获取节点 action
                    for (Iterator iterB = elementA.elementIterator(); iterB
                            .hasNext(); ) {
                        Element elementB = (Element) iterB.next();
                        if (elementB != null && "action".equals(elementB.getName())) {
                            Attribute attrB_key = elementB.attribute("key");
                            String key = attrB_key.getText().toUpperCase();

                            // create action
                            Action action = new Action(key);

                            Attribute attrB_text = elementB.attribute("text");
                            if (attrB_text != null) {
                                action.setText(attrB_text.getText());
                            } else {
                                action.setText(key);
                            }

                            Attribute attrB_note = elementB.attribute("note");
                            if (attrB_note != null) {
                                action.setNote(attrB_note.getText());
                            }

                            globalActionMap.put(key, action);
                        }
                    }// action end
                }// globalActions end
                else if ("permissions".equals(elementA.getName())) {
                    // 获取节点 permission
                    for (Iterator iterB = elementA.elementIterator(); iterB
                            .hasNext(); ) {
                        Element elementB = (Element) iterB.next();
                        if (elementB != null && "permission".equals(elementB.getName())) {
                            Attribute attrB_menuId = elementB.attribute("menuId");
                            String menuId = attrB_menuId.getText();
                            String menuName = MenuHelper.getInstance().getMenuName(menuId);
                            if(menuName == null){
                                continue;
                            }

                            // create permission
                            Permission permission = new Permission(
                                    menuId, menuName);

                            Attribute attrB_actions = elementB.attribute("actions");
                            if (attrB_actions != null) {
                                String actionsString = attrB_actions.getText();
                                if (StringUtils.isNotBlank(actionsString)) {
                                    String[] actionKeys = actionsString.split(",");
                                    for (String aKey : actionKeys) {
                                        if (globalActionMap.containsKey(aKey)) {
                                            Action g_action = globalActionMap.get(aKey);
                                            Action action = new Action(g_action.getKey().toUpperCase());
                                            action.setText(g_action.getText());
                                            action.setNote(g_action.getNote());
                                            action.setMenuId(permission.getMenuId());
                                            action.setMenuName(permission.getMenuName());
                                            permission.getActionList().add(action);
                                            actionArray.add(action);
                                        }
                                    }
                                }
                            }

                            /* 循环action节点 */
                            if (elementB.hasContent()) {
                                List<Action> actionList = permission.getActionList();
                                // 获取节点 action
                                for (Iterator iterC = elementB.elementIterator(); iterC
                                        .hasNext(); ) {
                                    Element elementC = (Element) iterC.next();
                                    if (elementC != null) {
                                        Attribute attrC_key = elementC.attribute("key");
                                        String aKey = attrC_key.getText().toUpperCase();
                                        Action action = new Action(aKey, permission.getMenuId());

                                        Attribute attrC_note = elementC.attribute("note");
                                        if (attrC_note != null) {
                                            action.setNote(attrC_note.getText());
                                        }

                                        /* 先判断permission的actionList中是否已经存在 */
                                        if (actionList.contains(action)) {
                                            actionList.remove(action);
                                            actionArray.remove(action);
                                        }

                                        /* 先默认设置为key的值 */
                                        String aText = aKey;

                                        /* 然后如果globalActionMap中有，使用其text值 */
                                        if (globalActionMap.containsKey(aKey)) {
                                            aText = globalActionMap.get(aKey).getText();
                                        }

                                        /* 最后如果action本身也设置了text属性，则覆盖之前所有 */
                                        Attribute attrC_text = elementC.attribute("text");
                                        if (attrC_text != null) {
                                            aText = attrC_text.getText();
                                        }

                                        action.setText(aText);
                                        action.setMenuName(permission.getMenuName());

                                        /* 会改变顺序 */
                                        actionList.add(action);
                                        actionArray.add(action);
                                    }
                                }
                                // action end
                            }
                            permissionsMap.put(attrB_menuId.getText(), permission);
                        }
                    }// permission end
                }// permissions end


            }
        }//permission-alice end
    }

}
